/***************************************************
 ** @Desc : This file for 代付
 ** @Time : 2019.04.10 15:51 
 ** @Author : Joker
 ** @File : pay
 ** @Last Modified by : Joker
 ** @Last Modified time: 2019.04.10 15:51
 ** @Software: GoLand
****************************************************/
package controllers

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"recharge/controllers/implement"
	"recharge/models"
	"recharge/sys"
	"recharge/utils"
	"recharge/utils/interface_config"
	"strings"
)

type Pay struct {
	KeepSession
}

var payMdl = models.WithdrawRecord{}
var payImpl = implement.RechargePayImpl{}
var sms = utils.SendMessages{}

// 展示代付页面
// @router /merchant/show_pay/ [get,post]
func (the *Pay) ShowPay() {
	userName := the.GetSession("userName")
	if userName != nil {
		the.Data["userName"] = userName.(string)
	}
	right := the.GetSession("FilterRight")
	if right != nil {
		the.Data["right"] = right.(int)
	}

	//通道
	//the.Data["channel"] = utils.GetChannelType()

	the.TplName = "pay.html"
}

// 商户代付
// @router /merchant/do_pay/?:params [post]
func (the *Pay) DoRecharge() {
	userId := the.GetSession("userId").(int)

	//channel := the.GetString("channel")
	//merchant := the.GetString("merchant")
	accountNo := strings.TrimSpace(the.GetString("accountNo"))
	accountName := strings.TrimSpace(the.GetString("accountName"))
	mobileNo := strings.TrimSpace(the.GetString("mobileNo")) //验证码
	userType := the.GetString("userType")
	issuer := strings.TrimSpace(the.GetString("issuer"))
	accountType := the.GetString("accountType")
	bankNo := strings.TrimSpace(the.GetString("bankNo"))
	branchProvince := strings.TrimSpace(the.GetString("branchProvince"))
	branchCity := strings.TrimSpace(the.GetString("branchCity"))
	branchName := strings.TrimSpace(the.GetString("branchName"))
	money := strings.TrimSpace(the.GetString("money"))

	//获取客户端ip
	ip := the.Ctx.Input.IP()

	var msg = utils.FAILED_STRING
	var flag = utils.FAILED_FLAG

	msg, verify := payImpl.VerificationPayInfo(accountNo, accountName, money)
	if verify {

		//手机验证码或ip白名单判断
		code := the.GetSession("do_pay_code")
		msg, verify = payImpl.VerificationSmgOrIP(userId, code, ip, mobileNo)
		cookie := the.Ctx.GetCookie("do_pay_sms_cookie") //两分钟失效
		if cookie == "" {
			the.SetSession("do_pay_code", "")
			the.SetSession("do_pay_sms_cookie", "")
		}

		if verify {

			XFMerchant := merchantFactor.QueryOneMerchantForPay(money)
			if XFMerchant.MerchantNo == "" || XFMerchant.Id == 0 {
				msg = "请联系管理员更新代付通道"
			} else {

				record := models.WithdrawRecord{}
				record.UserId = userId
				record.MerchantNo = XFMerchant.MerchantNo

				record.SerialNumber = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(10)
				record.WhOrderId = utils.XF + globalMethod.GetNowTimeV2() + globalMethod.RandomString(8)

				yuanToFloat, _ := globalMethod.MoneyYuanToFloat(money)
				record.WhAmount = yuanToFloat
				record.WhUserType = userType
				record.WhAccountNo = accountNo
				record.WhAccountName = accountName

				if strings.Compare("2", userType) == 0 {
					accountType = "4"
				}
				record.WhAccountType = accountType

				record.WhBankNo = bankNo
				record.WhIssuer = issuer

				record.WhBranchProvince = branchProvince
				record.WhBranchCity = branchCity
				record.WhBranchName = branchName

				record.NoticeUrl = interface_config.XF_PAY_NOTICE_URL + record.WhOrderId

				nowTime := globalMethod.GetNowTime()
				record.CreateTime = nowTime
				record.EditTime = nowTime

				//状态以异步回调为准
				record.Status = utils.I

				// 多通道代付
				switch XFMerchant.ChannelType {
				case utils.XF:
					//先锋
					record.RecordType = utils.XF
					//判断可用余额,冻结提现金额
					enough, rMsg := userMdl.SelectOneUserUsableAmount(userId, yuanToFloat, record)
					if !enough {
						msg = rMsg
					} else {
						result, err := xfPay(record, XFMerchant.SecretKey)
						if err != nil {
							msg = err.Error()
						} else {

							resp := models.XFPayResponseBody{}
							err = json.Unmarshal(result, &resp)
							if err != nil {
								sys.LogError("orderId=", record.WhOrderId, ", response data format is error: ", err)
								msg = "先锋代付响应数据格式错误"
							} else {

								if strings.Compare("00000", resp.ResCode) == 0 ||
									strings.Compare("00001", resp.ResCode) == 0 ||
									strings.Compare("00002", resp.ResCode) == 0 {
									flag = utils.SUCCESS_FLAG
								} else {
									sys.LogDebug("先锋代付错误：", resp)
									msg = "先锋代付错误：" + resp.ResMessage
								}
							}
						}
					}
				}
			}
		}
	}

	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 代付发送短信验证码
// @router /merchant/do_pay_sms/?:params [post]
func (the *Pay) SendMsgDoPay() {
	accountNo := strings.TrimSpace(the.GetString("accountNo"))
	accountName := strings.TrimSpace(the.GetString("accountName"))
	money := strings.TrimSpace(the.GetString("money"))

	var msg = utils.FAILED_STRING
	var flag = utils.FAILED_FLAG

	msg, verify := payImpl.VerificationPayInfo(accountNo, accountName, money)
	if verify {
		loginName := the.GetSession("FilterUsers")
		if loginName == nil {
			msg = "浏览器请不要禁用cookie！"
		} else {
			u := userMdl.SelectOneUser(loginName.(string))
			ux := userExpandMdl.SelectOneUserInfoExpansion(u.Id)
			if ux.Ips != "" {
				msg = "已有IP白名单，无需发送验证码，输入任意字符即可！"
			} else {

				editCookie := the.Ctx.GetCookie("do_pay_sms_cookie")
				if editCookie == "" {
					the.SetSession("do_pay_sms_cookie", "")
				}

				cookieS := the.GetSession("do_pay_sms_cookie")
				codeCookie := ""
				if cookieS != nil {
					codeCookie = cookieS.(string)
				}

				if editCookie != "" || strings.Compare(editCookie, codeCookie) != 0 {
					msg = "请在2分钟后送登录验证码！"
				} else {
					code := globalMethod.RandomIntOfString(6)
					isSuccess := sms.SendSmsCode(u.Mobile, code)
					if !isSuccess {
						msg = "验证码发送失败，请联系管理员核实预留手机号是否正确！"
					} else {
						flag = utils.SUCCESS_FLAG
						the.SetSession("do_pay_code", code)

						cookie := globalMethod.RandomString(6)
						the.Ctx.SetCookie("do_pay_sms_cookie", cookie, 2*60)
						the.SetSession("do_pay_sms_cookie", cookie)

						msg = "验证码发送成功，且2分钟内有效！"
					}
				}
			}
		}
	}

	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 代付手动回调
// @router /merchant/pay_notice/?:params [get]
func (the *Pay) PayNotice() {
	queryId := the.GetString(":params")

	record := payMdl.SelectOneWithdrawRecord(queryId)

	var msg = utils.FAILED_STRING
	var flag = utils.FAILED_FLAG

	if strings.Compare(utils.S, record.Status) == 0 {
		info, _ := userMdl.SelectOneUserById(record.UserId)

		params := models.ApiResponseBody{}
		params.MerchantNo = fmt.Sprintf("%d", record.UserId)
		params.OutTradeNo = record.WhOrderId
		params.TradeStatus = utils.GetApiOrderStatus()[record.Status]
		params.TradeNo = record.SerialNumber
		params.TradeTime = record.EditTime
		params.Item = record.Item

		params.Amount = globalMethod.MoneyYuanToString(record.WhAmount + info.PayFee)
		params.AmountNotFee = globalMethod.MoneyYuanToString(record.WhAmount)
		params.AmountFee = globalMethod.MoneyYuanToString(info.PayFee)

		params.ResultCode = "0000"
		params.Msg = record.Remark

		sign := apiRPImpl.GenerateSignV1(params, info.ApiKey)
		params.Sign = sign

		//生成请求参数
		toMap := globalMethod.StructToMap(params)
		byMap := globalMethod.UrlEncode(toMap)

		//发送请求
		urls := record.ApiNoticeUrl + "?" + byMap
		sys.LogInfo("代付手动异步通知url=", urls)
		resp, err := http.Get(urls)
		if err != nil {
			sys.LogError("手动代付异步通知没有响应：", err, record.ApiNoticeUrl)
			msg = "手动代付异步通知没有响应"
		} else {

			body, err := ioutil.ReadAll(resp.Body)
			if err != nil {
				sys.LogError("手动代付异步通知响应错误：", err)
				msg = "手动代付异步通知响应错误"
			} else if strings.Compare(string(body), "SUCCESS") != 0 {
				sys.LogInfo("手动代付手动通知响应：", string(body))
				msg = "手动代付异步通知没有响应：SUCCESS"
			} else {
				flag = utils.SUCCESS_FLAG
				msg = "手动回调通知成功"
			}
			defer resp.Body.Close()
		}
	} else {
		msg = "只回调成功的订单！"
	}

	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 展示手动关单
// @router /user/hand_pay_record_ui/?:params [get]
func (the *Pay) ShowHandPayRecordUI() {
	editId := the.GetString(":params")
	the.SetSession("hand_pay_record_id", editId)

	the.Data["json"] = globalMethod.JsonFormat(utils.SUCCESS_FLAG, "", "", "")
	the.ServeJSON()
	the.StopRun()
}

// 代付手动关单
// @router /user/hand_pay_record/?:params [post]
func (the *Pay) HandPayRecord() {
	var (
		msg     = utils.FAILED_STRING
		flag    = utils.FAILED_FLAG
		record  models.WithdrawRecord
		queryId string
	)

	recordStatus := the.GetString("recordStatus")
	queryIds := the.GetSession("hand_pay_record_id")
	if queryIds == nil {
		goto back
	} else {
		queryId = queryIds.(string)
	}

	record = payMdl.SelectOneWithdrawRecord(queryId)
	if record.Status == "" || strings.Compare(record.Status, utils.I) == 0 {
		record.EditTime = globalMethod.GetNowTime()
		switch recordStatus {
		case "-1":
			record.Status = utils.F
			flag = userMdl.SelectOneUserDeductionForFail(record.UserId, record.WhAmount, record)
		case "1":
			record.Status = utils.S
			// 减款
			flag = userMdl.SelectOneUserDeductionForSuccess(record.UserId, record.WhAmount, record)
		default:
			msg = "订单状态非法！"
			goto back
		}
	} else {
		msg = "订单状态非法！"
	}

	if flag > 0 {
		//若是对接订单,发送异步通知
		if strings.Compare(utils.A, record.RecordClass) == 0 {
			go func() {
				apiNotice.ApiPayAsyNotice(record)
			}()
		}
		sys.LogInfo("先锋代付订单:", record.WhOrderId, "手动处理成功")
	} else {
		sys.LogInfo("先锋代付订单:", record.WhOrderId, "手动处理失败")
	}

back:
	the.Data["json"] = globalMethod.JsonFormat(flag, "", msg, "")
	the.ServeJSON()
	the.StopRun()
}

// 先锋代付
func xfPay(record models.WithdrawRecord, key string) ([]byte, error) {
	// 请求参数
	reqParams := url.Values{}
	reqParams.Add("service", "REQ_WITHDRAW")
	reqParams.Add("secId", interface_config.SECID)
	reqParams.Add("version", interface_config.VERSION)
	reqParams.Add("reqSn", record.SerialNumber)
	reqParams.Add("merchantId", record.MerchantNo)

	// 需要的加密参数
	dataParams := models.XFPayData{}
	dataParams.MerchantNo = record.WhOrderId
	dataParams.Source = "1"
	fen, _ := globalMethod.MoneyYuanToFen(record.WhAmount)
	dataParams.Amount = fen
	dataParams.TransCur = "156"
	dataParams.UserType = record.WhUserType
	dataParams.AccountNo = record.WhAccountNo
	dataParams.AccountName = record.WhAccountName
	dataParams.MobileNo = record.WhMobileNo
	dataParams.BankNo = record.WhBankNo

	terminalParams := models.TerminalParams{}
	terminalParams.MerEquipmentIp = globalMethod.RandIpAddr()
	ter, _ := json.Marshal(&terminalParams)
	dataParams.TerminalParams = string(ter)

	if strings.Compare("2", record.WhUserType) == 0 {
		dataParams.Issuer = record.WhIssuer
	}

	dataParams.BranchProvince = record.WhBranchProvince
	dataParams.BranchCity = record.WhBranchCity
	dataParams.BranchProvince = record.WhBranchName

	dataParams.NoticeUrl = record.NoticeUrl

	// 加密参数
	dataString, _ := json.Marshal(&dataParams)
	data, err := AES.AesEncrypt(string(dataString), key)
	if err != nil {
		return nil, err
	}

	reqParams.Add("data", data)

	// 生成签名
	respParams := map[string]string{}
	respParams["service"] = "REQ_WITHDRAW"
	respParams["secId"] = interface_config.SECID
	respParams["version"] = interface_config.VERSION
	respParams["reqSn"] = record.SerialNumber
	respParams["merchantId"] = record.MerchantNo
	respParams["data"] = data
	params := globalMethod.ToStringByMap(respParams)

	signBytes, err := merchantImpl.XFGenerateSign(params, key)
	if err != nil {
		s := "先锋代付生成签名失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	reqParams.Add("sign", string(signBytes))

	// 发送请求
	resp, err := http.PostForm(interface_config.XF_RECHANGE_URL, reqParams)
	if err != nil {
		s := "先锋代付请求失败"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	// 处理响应
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		s := "先锋代付响应为空"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}
	defer resp.Body.Close()

	bytes, err := AES.AesDecrypt(body, []byte(key))
	if err != nil {
		s := "先锋代付响应解密错误"
		sys.LogTrace(s, err)
		return nil, errors.New(s)
	}

	return bytes, err
}
